30. Spring2 - 获取对象, 容器的几种实现, bean 属性赋值, 属性赋值规则

applicationContext.xml 配置文件

<bean> 定义 Spring 所管理的一个对象,bean 中的 id 表示该对象的唯一标识 (使用 class 获取对象的时候可以不设置),不能重复。class 表示对象所属类的包名和类名。

<property> 表示为对象的某个属性赋值,name 表示属性名,value 表示属性值。

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="person" class="com.itguigu.spring.mod.Person">
<property name="id" value="1001"></property>
<property name="name" value="zhangsan"></property>
</bean>
</beans>

获取对象

方式1

1
2
3
// 获取对象(通过 id)
Person person = (Person) aContext.getBean("person");
System.out.println(person);

方式2

1
2
// 获取对象(通过 类名.class, 使用此方法获取对象时候,要求 Spring 所管理的此类型的对象只有一个)
Person person2 = aContext.getBean(Person.class);

方式3

1
2
// 获取对象(id + 类型)
Person person3 = aContext.getBean("person", Person.class);

容器在 Spring 中的实现

可以使用如下方式看到容器的结构图

ctrl + shift + t 能查询某个类

ctrl + t 能查看某个类的继承关系

ApplicationContext 的主要实现类

ClassPathXmlApplicationContext:对应类路径下的XML格式的配置文件

FileSystemXmlApplicationContext:对应文件系统中的XML格式的配置文件

在初始化时就创建单例的bean,也可以通过配置的方式指定创建的Bean是多实例的。

ConfigurableApplicationContext

是ApplicationContext的子接口,包含一些扩展方法

refresh()和close()让ApplicationContext具有启动、关闭和刷新上下文的能力。

WebApplicationContext

专门为WEB应用而准备的,它允许从相对于WEB根目录的路径中完成初始化工作

bean 属性赋值

通过依赖注入的方式

Student 类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package com.itguigu.spring.di;

public class Student {
private Integer id;
private String name;
private Integer age;
private String sex;
private Double score;

public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}

public Double getScore() {
return score;
}
public void setScore(Double score) {
this.score = score;
}

@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", age=" + age + ", sex=" + sex + ", score=" + score + "]";
}

public Student(Integer id, String name, Integer age, String sex) {
super();
this.id = id;
this.name = name;
this.age = age;
this.sex = sex;
}

public Student() {
super();
}

public Student(Integer id, String name, Double score, String sex) {
super();
this.id = id;
this.name = name;
this.score = score;
this.sex = sex;
}
}
set 注入
1
2
3
4
5
6
7
<!-- 通过 set 方法为属性赋值  -->
<bean id="s1" class="com.itguigu.spring.di.Student">
<property name="id" value="1001"></property>
<property name="name" value="zhangsan"></property>
<property name="age" value="23"></property>
<property name="sex" value="男"></property>
</bean>
构造方法注入
1
2
3
4
5
6
7
<!-- 通过构造方法为属性赋值  -->
<bean id="s2" class="com.itguigu.spring.di.Student">
<constructor-arg value="10086"></constructor-arg>
<constructor-arg value="lisi"></constructor-arg>
<constructor-arg value="45"></constructor-arg>
<constructor-arg value="女"></constructor-arg>
</bean>
1
2
3
4
5
6
7
<!-- 验证构造方法有多个存在可能混淆的时候,采用 index + type 进行赋值  -->
<bean id="s3" class="com.itguigu.spring.di.Student">
<constructor-arg value="10022"></constructor-arg>
<constructor-arg value="wangwu"></constructor-arg>
<constructor-arg value="90" index="2" type="java.lang.Double"></constructor-arg>
<constructor-arg value="女"></constructor-arg>
</bean>

验证结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.itguigu.spring.di;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans-di.xml");

// 验证 set 方法赋值
Student student1 = applicationContext.getBean("s1", Student.class);
System.out.println(student1); // Student [id=1001, name=zhangsan, age=23, sex=男, score=null]

// 验证构造方法赋值
Student student2 = applicationContext.getBean("s2", Student.class);
System.out.println(student2); // Student [id=10086, name=lisi, age=45, sex=女, score=null]

// 验证构造方法有多个存在可能混淆的时候,采用 index + type 进行赋值
Student student3 = applicationContext.getBean("s3", Student.class);
System.out.println(student3); // Student [id=10022, name=wangwu, age=null, sex=女, score=90.0]
}
}

P 命名空间

引入 P 命名空间 xmlns:p=*"**http://www.springframework.org/schema/p**"*

1
2
<!-- P 命名空间  -->
<bean id="s4" class="com.itguigu.spring.di.Student" p:age="20" p:id="10098" p:name="zhaoliu" p:score="99"></bean>

bean 属性赋值的规则

字面量

给 bean 属性赋值的时候,如果 bean 属性的类型是基本数据类型及其封装类、String等类型,那么赋的值可以是字符串(字面量),若赋的值包含特殊字符,可以使用<![CDATA[]]>把字面值包裹起来。使用字符串赋值的时候,可以使用 value 属性或 value 子节点的方式来指定。

例如:

1
2
3
4
5
6
7
<!-- 通过 set 方法为属性赋值  -->
<bean id="s1" class="com.itguigu.spring.di.Student">
<property name="id" value="1001"></property>
<property name="name" value="zhangsan"></property>
<property name="age" value="23"></property>
<property name="sex" value="男"></property>
</bean>

这里面的 id 在 Student 中是 Integer 类型的,属于基本数据类型及其封装类,那么赋的值就可以是字符串,且可以使用 value 属性或 value 子节点的方式来指定。

1
<property name="id" value="1001"></property>
1
2
3
<property name="id">
<value>1001</value>
</property>

引用其他 bean

反之,如果bean 属性的类型不是基本数据类型及其封装类、String等类型,那么就不能采用这种方法就行赋值。例如 Student 里面有一个 Teacher 的对象,Teacher 数据应用数据类型,不满足上述条件,那么就不能使用字符串的方式进行赋值,这时得使用 ref 的方式,引用其他的 bean。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- 通过 ref 为 bean 的应用数据类型属性赋值 -->
<bean id="s5" class="com.itguigu.spring.di.Student">
<property name="id" value="1001"></property>
<property name="name" value="zhangsan"></property>
<property name="age" value="23"></property>
<property name="sex" value="男"></property>
<property name="score" value="99"></property>
<property name="teacher" ref="teacher"></property>
</bean>

<bean id="teacher" class="com.itguigu.spring.di.Teacher">
<property name="tname" value="王老师"></property>
<property name="tage" value="66"></property>
</bean>

null 值

1
2
3
4
5
6
7
8
<bean class="com.atguigu.spring.bean.Book" id="bookNull" >
<property name"bookId" value ="2000"/>
<property name"bookName">
<null/>
</property>
<property name"author" value ="nullAuthor"/>
<property name"price" value ="50"/>
</bean >

内部 bean

定义在某个 bean 内部的 bean,只能在当前 bean 中使用,其他 bean 是无法引用此 bean 的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- 内部 bean -->
<bean id="s6" class="com.itguigu.spring.di.Student">
<property name="id" value="1001"></property>
<property name="name" value="zhangsan"></property>
<property name="age" value="23"></property>
<property name="sex" value="男"></property>
<property name="score" value="99"></property>
<property name="teacher">
<!-- 定义在某个 bean 内部的 bean,只能在当前 bean 中使用,其他 bean 是无法引用此 bean 的。 -->
<bean id="ttt" class="com.itguigu.spring.di.Teacher">
<property name="tname" value="李老师"></property>
<property name="tage" value="99"></property>
</bean>
</property>
</bean>

代码地址